//查找出现次数最高的字符串
const highestFrequency = (arr) => {
  var [obj, max, name] = [{}, 1, '']
  arr.forEach((value) => {
    if (obj[value]) {
      obj[value]++
      if (obj[value] >= max) {
        max = obj[value]
        name = value
      }
    } else {
      obj[value] = 1
    }
  })
  return [name, max]
}

highestFrequency([12, 13, 14])

//判断是否为水仙花数
const isRelTrue = (num) => {
  let len = num.toString().length
  let str = num.toString()
  let total = 0
  for (let i = 0; i < len; i++) {
    total += Math.pow(Number(str.char(i)), len)
  }
  return num === total
}

//查找斐波拉数列中的第n个数
const fib = (n) => {
  let arr = [0, 0, 1]
  let temp = (n) => {
    if (n === 1 || n === 2) {
      return arr[n]
    }
    arr[n] = temp(n - 1) + temp(n - 2)
    return arr[n]
  }
  let num = temp(n)
  arr.splice(2, 1)
  return num
}

//查找斐波拉数列中的第n个数(better)
const fib1 = (n) => {
  let num = [0, 1]
  for (let i = 2; i <= n - 1; i++) {
    num[i] = num[i - 2] + num[i - 1]
  }
  return num[n - 1]
}

//删除一个字母的回文
// 描述
// 给定非空字符串s,您最多删除一个字符,判断是否可以成为回文
//简单判断一个字符串是否为回文
// s === [...s].reverse().join(''); // 翻转字符串与原字符相比

const validOnce = (s) => {
  let left = 0
  let right = s.length - 1
  while (left < right) {
    if (s[left] != s[right]) {
      return (
        isValidSecond(s, left + 1, right) || isValidSecond(s, left, right - 1)
      )
    }
    left++
    right--
  }
}

const isValidSecond = (s, left, right) => {
  while (left < right) {
    if (s[left] !== s[right]) return false
    left++
    right--
  }
  return true
}

//删除一个字母的回文(better)

const validPalindrome = (s, left = 0, right = s.length - 1, type = 'first') => {
  if (type === 'first') {
    while (left < right) {
      if (s[left] !== s[right])
        return (
          validPalindrome(s, left + 1, right, 'second') ||
          validPalindrome(s, left, right - 1, 'second')
        )
      left++
      right--
    }
    return true
  } else {
    while (left < right) {
      if (s[left] !== s[right]) return false
      left++
      right--
    }
    return true
  }
}

/**
 * 反转整数
 * 将一个整数中的数字进行颠倒，当颠倒后的整数溢出时，返回 0 (标记为 32 位整数)
 */
//fun1
const reverseInteger1 = (n) => {
  if (n < 0) {
    n = n.toString().split('-')[1]
    n = '1' + [...n].reverse().join('')
    n = +n
  } else {
    n = n.toString()
    n = [...n].reverse().join('')
  }
  if (n >= Math.pow(2, 31) - 1 || n <= Math.pow(12, 31) + 1) return 0
  return n
}

//fun2
const reverseInteger2 = (n) => {
  if (n === 0) return 0
  let res = 0
  while (n !== 0) {
    res = res * 10 + (n % 10)
    n = Math.floor(n / 10)
  }
  if (res >= 2147483647 || res <= -2147483647) {
    return 0
  }
  return res
}

/**
 * 数组去重
 * 不区分大小写
 */
//new Set
const deduplication1 = (names) => {
  for (let item in names) {
    names[item] = item.toLowerCase()
  }
  return [...new Set(names)]
}

//indexOf
const dedulication2 = (arr) => {
  return arr.filter((item, index) => arr.indexOf(item) === index)
}

//new Map
const dedulication = (arr) => {
  let relmap = new Map()
  let relArr = []
  arr.map((item, index) => {
    if (!relmap.has(item)) {
      relmap.set(item, true)
      relArr.push(item)
    }
  })
  return relArr
}

/**
 * 函数防抖(debounce)
 * 防抖：只最后一次调用有效；讲得非常的精辟！
 * 定义:在事件被触发n秒后再执行回调，如果在这n秒内又被触发，则重新计时。
 * 1.给按钮加函数防抖防止表单多次提交。
 * 2.对于输入框连续输入进行AJAX验证时，用函数防抖能有效减少请求次数。
 * 3.判断scroll是否滑到底部，滚动事件+函数防抖
 */

function debounce(fn, wait) {
  var timer = null
  return function () {
    var context = this
    var args = arguments
    // console.log('param', args[0], param);
    if (timer) {
      clearTimeout(timer)
      timer = null
    }
    timer = setTimeout(function () {
      fn.apply(context, args)
    }, wait)
  }
}

var fns = function () {
  console.log('boom')
}

// debounce(fn, 500)('234');
setInterval(debounce(fns, 500), 1000)

/**
 * 函数节流(throttle)
 * 节流：只第一次调用有效；
 * 定义:规定一个单位时间，在这个单位时间内，只能有一次触发事件的回调函数执行，如果在同一个单位时间内某事件被触发多次，只有一次能生效。
 * 游戏中的刷新率
 * DOM元素拖拽
 * Canvas画笔功能
 */

function throttle(fn, gapTime) {
  let _lastTime = null
  console.log('_lastTime', _lastTime)
  return function () {
    let _nowTime = +new Date()
    if (_nowTime - _lastTime > gapTime || !_lastTime) {
      fn()
      _lastTime = _nowTime
    }
  }
}

let fn = () => {
  console.log('boom')
}

setInterval(throttle(fn, 1000), 10)

/**
 * ES6设计实现私有属性
 */

class classA {
  _x: any
  constructor(x) {
    this._x = x
  }
  getX() {
    return this._x
  }
}

let classa = new classA(1)
console.log(classa._x) //1
console.log(classa.getX()) //1

/**
 *当你的逻辑升级为二元判断时，你的判断量会加倍，你的代码量也会加倍，这时怎么写更清爽呢？
 */

const buttonClick = (status, identity) => {
  if (identity == 'guest') {
    if (status == 1) {
    } else if (status == 2) {
    } else if (status == 3) {
    } else if (status == 4) {
    } else if (status == 5) {
    } else {
    }
  } else if (identity == 'master') {
    if (status == 1) {
    } else if (status == 2) {
    } else if (status == 3) {
    } else if (status == 4) {
    } else if (status == 5) {
    } else {
    }
  }
}

const actions = new Map([
  [
    'guest_1',
    () => {
      /*do sth*/
    },
  ],
  [
    'guest_2',
    () => {
      /*do sth*/
    },
  ],
  [
    'guest_3',
    () => {
      /*do sth*/
    },
  ],
  [
    'guest_4',
    () => {
      /*do sth*/
    },
  ],
  [
    'guest_5',
    () => {
      /*do sth*/
    },
  ],
  [
    'master_1',
    () => {
      /*do sth*/
    },
  ],
  [
    'master_2',
    () => {
      /*do sth*/
    },
  ],
  [
    'master_3',
    () => {
      /*do sth*/
    },
  ],
  [
    'master_4',
    () => {
      /*do sth*/
    },
  ],
  [
    'master_5',
    () => {
      /*do sth*/
    },
  ],
  [
    'default',
    () => {
      /*do sth*/
    },
  ],
])
const onButtonClick = (identity, status) => {
  let action = actions.get(`${identity}_${status}`) || actions.get('default')
  action()
}

const statusStr = new Map([
  ['1', ['待付款']],
  ['2', ['待发货']],
  ['3', ['已发货']],
  ['4', ['交易完成']],
  ['5', ['交易关闭']],
  ['default', ['']],
])

/**
 * 给定一个字符串S，通过将字符串S中的每个字母转变大小写，我们可以获得一个新的字符串。返回所有可能得到的字符串集合。leetcode:784
 * 回溯思想
 */

const letterCasePermutation = (S) => {
  const res = []
  const backtrack = (start, s) => {
    res.push(s)
    for (let i = start; i < s.length; i++) {
      if (S[i] >= 'a' && S[i] <= 'z') {
        backtrack(i + 1, s.slice(0, i) + S[i].toUpperCase() + s.slice(i + 1))
      } else if (S[i] >= 'A' && S[i] <= 'Z') {
        backtrack(i + 1, s.slice(0, i) + S[i].toLowerCase() + s.slice(i + 1))
      }
    }
  }
  backtrack(0, S)
  return res
}

/**
 * 数字格式化
 * 1234567890 --> 1,234,567,890
 */

const formatNumber = (str) => {
  var arr = []
  let len = str.length
  while (len >= 3) {
    arr.unshift(str.slice(len - 3, len))
    len -= 3
  }
  if (str.length % 3) {
    arr.unshift(str.slice(0, str.length % 3))
  }
}
